﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;

namespace Luna.Core.Extensions
{
    public static class EnumerableExtension
    {
        public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T> action)
        {
            foreach (var item in source)
            {
                action(item);
            }
            return source;
        }

        public static IEnumerable<T> ForEach<T>(
            this IEnumerable<T> source, Action<T> action, Predicate<T> condition)
        {
            foreach (var item in source)
            {
                if (condition(item))
                    action(item);
            }
            return source;
        }

        public static IEnumerable<T> For<T>(this IEnumerable<T> source, Action<int> action)
        {
            for (int i = 0; i < source.Count(); i++)
            {
                action(i);
            }
            return source;
        }

        public static bool EqualValue<T>(this IEnumerable<T> source1, IEnumerable<T> source2)
        {
            if (source1 == source2)
                return true;
            if (source1.Count() != source2.Count())
                return false;
            for (int i = 0; i < source1.Count(); i++)
            {
                if (!source1.ElementAt(i).Equals(source2.ElementAt(i)))
                    return false;
            }
            return true;
        }

        public static IEnumerable<T> Add<T>(this IEnumerable<T> source, T item)
        {
            foreach (var obj in source)
            {
                yield return obj;
            }
            yield return item;
        }

        public static IEnumerable<T> Remove<T>(this IEnumerable<T> source, T item)
        {
            foreach (var obj in source)
            {
                if (!obj.Equals(item))
                    yield return obj;
            }
        }

        public static IEnumerable<T> GetRange<T>(this IEnumerable<T> source, int start, int end)
        {
            int index = 0;
            int count = end - start + 1;
            bool begin = false;
            foreach (var item in source)
            {
                if (index == start)
                    begin = true;
                if (begin)
                {
                    if (count > 0)
                    {
                        yield return item;
                        count--;
                    }
                }
                index++;
            }
        }

        public static IDictionary<TKey, TSource> ToDistinctDictionary<TSource, TKey>(
            this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            Dictionary<TKey, TSource> dictionary = new Dictionary<TKey, TSource>(source.Count());
            foreach (var obj in source)
            {
                dictionary[keySelector(obj)] = obj;
            }
            return dictionary;
        }

        public static int Count(this IEnumerable source)
        {
            int count = 0;
            foreach (var o in source)
            {
                count++;
            }
            return count;
        }

        public static IEnumerable<T> ToEnumerable<T>(this IEnumerable source)
        {
            foreach (var o in source)
            {
                yield return (T)o;
            }
        }

        public static List<object> ToList(this IEnumerable source)
        {
            var enumerable = source.ToEnumerable<object>();
            return enumerable.ToList<object>();
        }
    }
}
